/*
 * Copyright (c) 2018-2024 北京华恒盛世科技有限公司
 * QUICKPOOL is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *     http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
*/

#ifndef JOB_MANAGER_H
#define JOB_MANAGER_H

#include "hash.h"
#include "xdrbase.h"
#include "channel.h"
#include "tclinfo.h"
#include "common.h"
#include "quickpool.h"
#include "lib.h"
#include "api.h"
#if defined (HAVE_HWLOC_H)
#include <hwloc.h>
#endif

typedef enum {
    STDOUT_DIRECT,
    JM_CONNTIMEOUT,
    JM_RECVTIMEOUT,
    GETPWNAM_RETRY,
    SIGNAL_SIGSTOP,
    COMPUTE_NODE,
    IGNORE_CHECKSUM,
    SPECIFY_NCPUS,
    RENICE_NEVER_AT_RESTART,
} jmparams_t;

#define NULLFILE "/dev/null"

#define QP_LOCK_FILE  "#quickpool.lock"

#define EXCHINTVL 	      15
#define UNRMPOLLINTVL         5
#define HOSTINACTIVITYLIMIT   5
#define MASTERINACTIVITYLIMIT 2
#define INACTIVITYRETRYLIMIT  2

#define JOB_SAVE_OUTPUT   0x10000000

#define WARN_TIME           600

#define JOB_FORCE_KILL    0x20000000
#define JOB_URGENT_NOSTOP 0x80000000

#define  EXP3   (double)0.716531311
#define  EXP4   (double)0.77880078
#define  EXP12  (double)0.920044415 
#define  EXP180 (double)0.994459848

extern int gintJMSleepTime;
extern int gintJsFd;
extern bool_t gboolJSReady;
extern struct config_param jmParams[];
extern char *gstrBossNode;
extern int gintUpdateUsagePercent;
extern int gintUpdateUsage;

extern struct loadIndex *gptrMyLoad;
extern pid_t gpidUnrm;
extern int gboolDefaultUnrm;
extern HASH_TABLE_T *ghashResource;

extern bool_t gboolJmCheckConfig;
extern int gintConfigError;


struct jobEntry {
    LIST_T *forw;
    LIST_T *back;
    struct jobInfo job_base;
    gid_t execute_gid;
#define JOB_EXEC_QPRE_OK          0x1
#define JOB_EXEC_QPRE_KNOWN       0x2
#define JOB_EXEC_STARTED          0x4
#define JOB_EXEC_FINISH           0x8
    unsigned int execute_flag;
    int comm_failcnt;
    time_t winclose_time;
    bool_t active;
    bool_t runtime_passed;
    bool_t lost;
    bool_t status_reset;
    unsigned int running;
    int w_status;
    float cpu_time;
    int mig_times;
    time_t report_time;
    bool_t update_usage;
    struct jobResourceUsage *inst_usage;
    struct jobResourceUsage *max_usage;
    struct requirement *resume_cond;
    struct requirement *stop_cond;
    int susp_reason;
    int susp_subreason;
    int actcmd_state;
    bool_t post_started;
    bool_t succeed;
    time_t chkpnt_time;
    struct lenData *job_file;
};

struct jobTask {
    LIST_T *forw;
    LIST_T *back;
    JOBID_T jobid;
    int options;
    char *from_node;
    int port;
    int conn_fd;
    int node_rank;
    int num_task;
    uid_t execute_uid;
    char *execute_user;
    char *cwd;
    char *script;
    gid_t execute_gid;
    pid_t task_pid;
    pid_t task_pgid;
    time_t start_time;
    time_t end_time;
    time_t report_time;
    bool_t update_usage;
    struct jobResourceUsage *task_usage;
    int w_status;
    int exit_code;
    int comm_failcnt;
    char **task_argv;
    int reason;
};

#define JOB_RUNNING(job) (((job)->job_base.status & JOB_STATUS_RUN) && (JOB_STARTED(job)))

#define JM_SET_STATE(job, n) { \
    (job->job_base.status) = ((job->job_base.status) & ~(MASK_QP_JOB_STATUS)) | (n); \
    jmlog_newstatus(job);}

extern int nClusAdmins;
extern uid_t *clusAdminIds;
extern uid_t *clusAdminGids;
extern char **clusAdminNames;

extern float exchIntvl;
extern short gintInactivityLimit;
extern short gintMasterInactLimit;
extern short gintInactiveRetryLimit;
extern int gintJobTerminateInterval;
extern bool_t gboolStdoutDirect;

extern int gintJmQuit;
extern bool_t gboolJmRestart;

#define MAXCANDHOSTS 10
#define MIN_FLOAT16  2.328306E-10

struct staticInfo {
    int maxcpu;
    double maxmem;
    double maxswap;
    double maxtmp;
    char *host_type;
    char *host_arch;
    numa_obj_t *numa;
};

struct hostNode {
    LIST_T *forw;
    LIST_T *back;
    char *name;
    short model_index;
    short type_index;
    short index;
    u_short naddr;
    in_addr_t *addr;
    struct staticInfo static_info;
    char *run_window;
    LIST_T *run_winlist;
    time_t winclose_time;
    server_t server;
    u_short number_resource;
    short noload_count;
    int *status;
    double *busy_threshold;
    double *load;
    char conStatus;
    unsigned int seq_number;
    int max_jobs;
    int *res_bitmap;
    HASH_TABLE_T *inst_table;
    bool_t call_unrm;
    unsigned int num_GPU;
    struct hostGPUList *gpuinfo_static;
    struct hostGPULoad *gpuinfo_dynamic;
};

#define CLUST_ACTIVE		0x00010000
#define CLUST_INFO_AVAIL  	0x00080000
#define CLUST_ALL_ELIGIBLE 	0x00400000

struct cluster {
    char *name;
    int status;
    int number_inactivity;
    struct hostNode *boss_node;
    u_short checksum;
    uid_t main_adminid;
    char *main_admin;
    HASH_TABLE_T *node_table;
    unsigned int num_clients;
    char **unrm_argv;
    unsigned int num_admins;
    uid_t *adminids;
    char **admins;
    int *res_bitmap;
    unsigned int num_numeric_resources;
    char **numeric_resource_names;
    int *type_bitmap;
    int *model_bitmap;
    unsigned int num_GPU;
};

#define LOOP_ADDR       0x7F000001

struct loadIndex {
    bool_t increasing;
    float delta[2];
    float sigdiff;
    double busy_value;
    double value;
};

struct sharedResource {
    struct resource_definition *resource;
    unsigned int flags;
    int index;
    LIST_T *inst_list;
};

struct resourceInstance {
    LIST_T *forw;
    LIST_T *back;
    struct resource_definition *resource;
    unsigned int flags;
    HASH_TABLE_T *node_table;
    char *org_value;
    char *value;
    time_t update_time;
    struct hostNode *update_host;
};

#define JOB_STARTED(job)  (((job)->execute_flag & JOB_EXEC_STARTED))

extern char gboolCheckFinishJobs;
extern char gboolCheckFinishTasks;
extern char *gstrEnvDir;
extern time_t gtimeNodeBoot;
extern uid_t guidManager;

extern LIST_T *glistJmJobs;
extern LIST_T *glistJobTask;

extern struct cluster *gptrMyCluster;
extern struct hostNode *gptrMyHost;
extern bool_t gboolMaster;
extern bool_t gboolMasterCand;
extern time_t gtimeJmStart;

#if defined (HAVE_HWLOC_H)
extern hwloc_topology_t topology;
#endif

/* socket handler functions are defined in handlesocket.c */
extern void handle_jsready(int, struct header *, XDR *);
extern void handle_newjob(int, struct header *, XDR *);
extern void handle_switchjob(int, struct header *, XDR *);
extern void handle_modifyjob(int, struct header *, XDR *);
extern void handle_signaljob(int, struct header *, XDR *);
extern void handle_start_jobtask(int, struct header *, XDR *, struct sockaddr_in *);
extern void handle_signal_jobtask(int, struct header *, XDR *, struct sockaddr_in *);
extern void handle_probe(int, struct header *, XDR *);
extern void handle_restart_reply(int, struct header *, XDR *);
extern void handle_reboot(int, struct header *, XDR *, struct auth *);
extern void handle_static_info(int, struct header*, XDR *, struct sockaddr_in *);
extern void handle_load_update(int, struct header*, XDR *, struct sockaddr_in *);
extern void handle_jm_debug(int, struct header *, XDR *, struct auth *);
extern void handle_shutdown(int, struct header *, XDR *, struct auth *);
extern void handle_job_setup(int, struct header *, XDR *);
extern void handle_info_req(int, struct header*, XDR *, struct sockaddr_in *);
extern void handle_clusterinfo_req(int, struct header*, XDR *, struct sockaddr_in *);
extern void handle_clustername_req(int, struct header*, XDR *, struct sockaddr_in *);
extern void handle_masterinfo_req(int, struct header*, XDR *, struct sockaddr_in *);
extern void handle_hostinfo_req(int, struct header*, XDR *, struct sockaddr_in *);
extern void handle_load_req(int, struct header*, XDR *, struct sockaddr_in *);
extern void handle_resourceinfo_req(int, struct header*, XDR *, struct sockaddr_in *);
extern void handle_add_dynamic(int, struct header *, XDR *, struct sockaddr_in *, struct auth *);
extern void handle_delete_dynamic(int, struct header *, XDR *, struct sockaddr_in *, struct auth *);
extern struct hostNode *add_hostnode(struct request *, char *);
extern int log_addnode(struct request *);

/* communication functions are defined in communicate.c */
extern int status_job(js_request_t, struct jobEntry *, int, unsigned int);
extern void notify_startup(void);
extern void childjm_set_jobstatus(int, int, struct jobEntry *);
extern void send_myload(void);

/* job handler functions are defined in handlejob.c */
extern int fork_2start_job(struct jobEntry *);
extern int job_finish (struct jobEntry *);
extern void putjob_injmJL(struct jobEntry *);
extern int create_jmjob(struct jobEntry *, struct jobInfo *, int *);
extern void delete_jmjob(struct jobEntry *);
extern struct requirement *check_threshold(char *);
extern void status_report(time_t);
extern void reset_jobstatus(struct jobEntry *);
extern int renice_job(struct jobEntry *);
extern void jobpid_lost(struct jobEntry *);
extern int set_userid_4job(JOBID_T, char *, uid_t, uid_t);
extern char **set_startjob_arguments(char *, char **);
extern int prepare_4postcmd(struct jobEntry *);
extern int execute_queue_postcmd(struct jobEntry *);
extern void get_tmpdir_4job(char *, JOBID_T, uid_t);
extern int jmlog_newstatus(struct jobEntry *);
extern int jmread_jobstatus (struct jobEntry *);
extern int set_execute_user(struct jobEntry *);

/* task handler functions are defined in handletask.c */
extern int fork_2start_jobtask(struct jobTask *);
extern void check_finish_tasks(void);
extern int kill_task_pg(struct jobTask *, int);
extern void read_job_acct(struct jobEntry *);

/* job checking functions are defined in handlepolicy.c */
extern void check_jmjobs(time_t);
extern void check_finish_jobs(void);

/* job file related functions are defined in handlefile.c */
extern int rcp_file(struct jobInfo *, struct execution_file *, char *, int, char *);
extern int remove_jobfile(struct jobEntry *);
extern int setup_path_4job(struct jobEntry *, struct lenData *);
extern int remove_dir_withfiles(char *, int);

/* internal.c */
extern void initialize_master(void);
extern void check_time_window(void);
extern int is_clusteradmin(char *);
extern struct hostNode *find_node_byaddr(struct sockaddr_in *, const char *);

/* jm die and relaunch are defined in jm.main.c */
extern void jm_die(int);
extern void relaunch(void);

/* job singal handler functions are defined in handlesignal.c */
extern int signal_job_begin(struct jobEntry *, int, int, bool_t);
extern int execute_suspend_command(struct jobEntry *, int ,int ,int, int, bool_t);
extern int take_resume_action(struct jobEntry *, int, bool_t);
extern int send_signal_2job(struct jobEntry *, int, int);
extern char *get_chkpnt_dir(const char *, char *);
extern char *get_exitfile_suffix(int);

/* getting system info functions are defined in linux.c */
extern int get_cores(void);
extern int get_system_load(double *, double *, double *);
extern double get_cputime(double *, double *);
extern unsigned long long int get_freemem(void);
extern unsigned long long int get_freeswap(void);
extern unsigned long long int get_maxmem(void);
extern unsigned long long int get_maxswp(void);
extern unsigned long long int get_availtmp(void);
extern double get_paging(double);
extern double iorate(double);
extern int get_memswap(void);
extern void get_gpu_info(void);
extern char *get_hosttype(void);
extern char *get_hostmodel(void);

/* node collector functions are defined in collector.c */
extern int init_nrm_info(bool_t);
extern void free_numanode(numa_obj_t *);
extern struct hostNode *create_hostnode(void);
extern void free_hostnode(struct hostNode *);
extern int get_hosttype_index(const char *);
extern int get_hostmodel_index(const char *);
extern void set_static_info(void);
extern void getload_andsend(void);
extern void set_unrm_caller(void);
extern void smooth(double *, double, double);

/* cgroup related functions are defined in handlecgroup.c */
extern int cgroup_setup_job_entry(JOBID_T, pid_t, const char *);
extern void setup_mem_cgroup(struct jobEntry *);
extern int cgroup_rm_job_entry(JOBID_T, const char *);
extern struct jobResourceUsage *cgroup_get_job_rusage(JOBID_T);

/* xdr function for node static information is defined in handlexdr.c*/
extern bool_t jm_xdr_staticinfo(XDR *, void *, struct header *, void *);

/* lockfile related functions are defined in lockfile.c*/
extern bool_t get_lock(void);
extern void release_lock(int);
extern void update_lock(void);

#endif
